iT邦幫忙

2024 iThome 鐵人賽

DAY 2
0
Modern Web

使用 Three.js 打造酷酷 3D 網頁體驗系列 第 2

[使用 Three.js 打造酷酷 3D 網頁體驗] 凡事都有個 Hello, World!

  • 分享至 

  • xImage
  •  

https://i.redd.it/kdedy7bsu2s71.jpg

上一篇介紹了 Three.js、render、還有 shader 的基本概念,今天我們馬上來把手弄髒吧!

在學習任何語言都會有一個 Hello, World! ,而 Three.js 框架的第一個專案,我們可以簡單建立一個場景,今天我們就手把手的建立專案、同時一邊學習一個「場景」有什麼必備的要素。

專案設定

開發 JavaScript 的專案非常的簡便,只需要使用任一個熟悉的編輯器跟 npm (node package manager) 就可以,在此使用 Visual Studio Code,vs code 相信我也不需多做介紹,已經是很多人在用的 IDE,針對不同語言與需求,他提供許多延伸模組使得開發流程更便利。

在視窗下方選擇 終端機、或是直接使用電腦本身的終端機,首先確定 nodenpm 都有正確下載。只要叫的到版本,就代表有安裝好囉!沒有的話可以根據作業系統尋找下載方法,這邊就不多做贅述。

% node --version
v21.7.1
% npm --version
10.7.0

接著,在安裝 three.js library 之前,我想說如果在開發的時候可以有 hot module replacement,也就是在 local run server 的時候,每次改動程式碼,網頁可以更新、不需要關掉重開 server 會是一個很重要的功能,同時我們也不想要裝一堆笨重的 module,希望可以維持在輕量級的開發。因此依賴 Vite 這個前端的工具會是一個不錯的選擇!

% npm create vite@latest [project_name] --template vanilla

這邊的 template/ framework 我們選擇 vanilla javascript,先從最基本的語法開始練習吧。等安裝好就可以進入專案資料夾中,安裝 three.js。

% cd [project_name]
% npm i three

這個時候可以先跑跑看,測試我們新建好的專案能不能運行。這邊的語法對應到 package.json 設定檔的 script。(比如初始應該有 devbuildpreview

% npm run dev

等到終端機跳出 ready 的訊息時,在瀏覽器貼上 URL,確認有以下畫面就沒問題了!

https://webcontainers.io/assets/1-vite-welcome-screen.7c25f95b.png

第一個場景

每一個畫面,可以想成是算圖工具使用攝影機場景裡的東西畫出來**,因此我們需要這四個元件就可以完成 Three.js 的 Hello, World! 啦!!

  1. 裝放物體、燈光、模型、粒子等的場景
  2. 想要畫的物件,比如說幾何形狀、模型等
  3. 拍攝這個場景的攝影機
  4. 把這些東西寫入畫面的 renderer

首先進入 main.js 把多餘的程式刪掉,只需要留下引入 library 的部分,還有像是 counter.js 和靜態資源如圖片等用不到的檔案也移除。

// main.js
import * as THREE from 'three'

場景 Scene

場景基本上就是一個容器,把想畫的東西放入後,晚點 renderer 會把場景裡的畫面畫出來。最最基本的第一步,我們先新增一個初始設定的場景,背景顏色會是黑色。

const scene = new THREE.Scene()

如果想要增加更詳細的設定,比如說改變背景的顏色或材質,都可以在寫得很完整的官方文件找到!

物件 Objects

在 JavaScript 裡,我們知道除了基本的數字、布林值等之外,其他萬物皆物件。這邊指的物件是 Three 有一些先定義好的,比如說幾何形狀、模型、燈光等。

https://docs.blender.org/manual/en/latest/_images/modeling_meshes_primitives_all.png

一般開發最常用的模型是使用 mesh 的型態,可以想像成用許多三角形或四邊形拼成的幾何體,這其中的三角形,都有頂點材質(比如說顏色、反光跟粗糙程度),我們同樣可以在官方文件找到相關的資料。


const geometry = new THREE.BoxGeometry(1, 1, 1)
const material = new THREE.MeshBasicMaterial({ color: 0xff0000 })
const mesh = new THREE.Mesh(geometry, material)

scene.add(mesh)

所以我們在場景中加入一個簡單的 Mesh 其中包含長寬高各等於 1 的 BoxGeometry ,以及一個基本的材質 MeshBasicMaterial,僅提供顏色和一些簡單的參數可以調整。我們可以注意到 MeshBasicMaterial 傳入的參數為一個物件,在這邊的顏色是已經 Three 定義好的顏色 Class,可以使用顏色名稱如 red 來指定,或是直接參考 color class 的頁面。

相機 Camera

https://learnopengl.com/img/guest/2021/Frustum_culling/VisualCameraFrustum.png

相機比前兩個要素稍微複雜一些,在這邊我們先來定義相機是如何運作的:因為運算資源有限,相機則會把要運算的區域 (frustum) 定義出來。

在一般的 rendering 討論範圍中,相機可以被分成 perspective 跟 orthogonal 兩種。

Perspective Camera 與 Orthogonal Camera 的差別

https://defold.com/manuals/images/camera/projections.png

這兩種主要的相機類型的差異是在投影方式和視覺效果上。

Perspective Camera(透視相機)- 透視相機模擬人眼的視覺效果,物體隨著距離的增加而變小。這種相機通常用於需要真實感的場景,例如遊戲和模擬應用。

// Perspective Camera
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000)
camera.position.z = 5
  • fov(field of view 視場角/度):frustum 垂直方向上的視角
  • aspect(aspect ratio 長寬比):畫布的寬度除以高度
  • near(near plane):frustum 裡從相機到場景中最近可見物體的距離
  • far(far plane):frustum 裡從相機到場景中最遠可見物體的距離

Orthogonal Camera(正交相機)- 正交相機不會隨距離改變來縮放物體,所有物體的大小在視圖中都是一致的。這種相機通常用於工程圖、建築圖和一些2D遊戲,因為它不會產生透視變形。

// Orthogonal Camera
const aspectRatio = window.innerWidth / window.innerHeight
const camera = new THREE.OrthographicCamera(-aspectRatio * 5, aspectRatio * 5, 5, -5, 0.1, 1000)
camera.position.z = 5

  • left, right, top, bottom:frustum 上下左右的平面座標
  • near:從相機到場景中最近可見物體的距離
  • far:從相機到場景中最遠可見物體的距離

Renderer

太好了,經過一番寒徹骨,總算來到最後一步,將場景畫到畫布上。

在網頁加入畫布有許多做法,舉例來說,可以直接在 HTML 文件加上 <canvas> 再用document.querySelector 把 canvas 指定給 renderer。

我們這邊嘗試簡單一點的作法,直接在 js 生成 HTML 的節點。

const renderer = new THREE.WebGLRenderer()
renderer.setSize(window.innerWidth, window.innerHeight)
document.body.appendChild(renderer.domElement)

renderer.render(scene, camera)

此時發現 canvas 有一個白邊,因此我們加上 css 把網頁 body 的白邊剔除。別忘了在 vite 可以從 js 檔案直接導入 css

body {
  margin: 0;
}
import './style.css'
import * as THREE from 'three'
// ...

延伸練習

最後,根據前面的介紹,希望有興趣的人可以自己練習看看這些要求,看是不是能從官方文件或線上資源找到相對的程式碼。

  1. 更改背景的顏色成鮭魚色 (salmon)
  2. 把方塊改成圓錐體 (cone)
  3. 使用 orthographic camera,並試著調動參數,比如說相機位置看看變化為何

好的!那麼明天會把延伸練習的解答公布,同時我把今天完成完整的 js 程式碼放在下方,有興趣的人可以參考,覺得有稍稍幫助到、或是覺得 3D 蠻有趣的話,麻煩幫點個愛心,我們就明天再見~

import './style.css'
import * as THREE from 'three'

const scene = new THREE.Scene()
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000)

const renderer = new THREE.WebGLRenderer()
renderer.setSize(window.innerWidth, window.innerHeight)
document.body.appendChild(renderer.domElement)

const geometry = new THREE.ConeGeometry()
const material = new THREE.MeshBasicMaterial({ color: 0x00ff00 })
const cube = new THREE.Mesh(geometry, material)
scene.add(cube)

camera.position.z = 5
renderer.render(scene, camera)

https://ithelp.ithome.com.tw/upload/images/20240916/20168365AMUViCt4e2.png


上一篇
[使用 Three.js 打造酷酷 3D 網頁體驗] 簡介——平凡的工程師有一個做酷酷 3D 的夢想
下一篇
[使用 Three.js 打造酷酷 3D 網頁體驗] 封印解除——3D 動畫動起來吧
系列文
使用 Three.js 打造酷酷 3D 網頁體驗5
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言